//
//  terminal.m
//
//        Sample client for Terminal.app's Distributed Objects services.
//        Copyright 1994-1997, Apple Computer, Inc. All rights reserved.
//
//
//    This program opens a terminal window in the current directory. It's installed
//    in /usr/bin/terminal.
//
//    Author: sam streeper
//    Updated by: Barry Locklear, Grant Baillie
//
//    To compile:
//
//      cc -I/NextDeveloper/Headers/Apps terminal.m -framework Foundation -o terminal
//
//    Usage:
//	terminal [-shell] [-dir <dir>] [-noclose] [-env] [command]
//

#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
#import <stdio.h>
#import <mach/mach.h>
#import <servers/bootstrap.h>
#import "TerminalDOProtocol.h"

static void usage(void) {
    fprintf(stderr,"terminal: open a new Terminal.app window\n\n");
    fprintf(stderr,"Usage: terminal [-shell] [-dir <dir>] [-noclose] [-env] [command]\n");
    fprintf(stderr,"	-shell   - Run command from default shell\n");
    fprintf(stderr,"	-dir     - Specify working directory (default is current)\n");
    fprintf(stderr,"	-noclose - Retain window upon exit\n");
    fprintf(stderr,"	-env     - Export current environment\n");
    exit(-1);
}

static id<TSTerminalDOServices> lookupTerminalDOServer(void) {
    port_t sendMachPort;
    NSDistantObject *rootProxy = nil;
    id<TSTerminalDOServices> result;

    // First, try look up Terminal's DO object in the bootstrap server.
    // This is where the app registers it by default.
    if ((BOOTSTRAP_SUCCESS == bootstrap_look_up(bootstrap_port, "TerminalDO", &sendMachPort)) && (PORT_NULL != sendMachPort)) {
        NSConnection *conn = [NSConnection connectionWithReceivePort:[NSPort port] sendPort:[NSPort portWithMachPort:sendMachPort]];
        rootProxy = [conn rootProxy];
    }

    // If the previous call failed, the following might succeed if the user
    // logged in is running Terminal with the PublicDOServices user default
    // set.
    if (!rootProxy) {
        rootProxy = [NSConnection rootProxyForConnectionWithRegisteredName:@"TerminalDO" host:@""];
    }

    // We could also try to launch Terminal at this point, using
    // the NSWorkspace protocol.
    if (!rootProxy) {
        fprintf(stderr,"Can't connect to Terminal\n");
        exit(-1);
    }

    [rootProxy setProtocolForProxy:@protocol(TSTerminalDOServices)];
    result = (id<TSTerminalDOServices>)rootProxy;

    if ([result protocolVersion] < 0x10002) {
        fprintf(stderr,"Incompatible terminal protocol version\n");
        exit(-4);
    }

    return result;
}

int main(void) {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    id <TSTerminalDOServices> terminal = lookupTerminalDOServer();

    NSEnumerator *argsEnum = [[[NSProcessInfo processInfo] arguments] objectEnumerator];
    NSString *thisArg;

    int returnCode;
    NSMutableString *command = nil;
    NSDictionary *environment = nil;
    NSString *directory = nil;
    TSShellType shellType = TSShellNone;
    TSExitAction exitAction = TSCloseUnlessError;

    int winHandle;

    NSData *inputData = nil;
    NSData *outputData = nil;
    NSData *errorData = nil;


    thisArg = [argsEnum nextObject]; /* Skip the program name */

    if (nil == thisArg) {
        shellType = TSShellDefault;
    }

    // Run through the command-line arguments. We only set command to
    // something non-nil once we encounter an argument that isn't an
    // option. Once we've done this, though, we treat the rest of
    // the arguments as part of the command.
    //
    while(thisArg = [argsEnum nextObject]) {
        if (command) {
            [command appendFormat:@" %@", thisArg];
        }
        else if (![thisArg hasPrefix:@"-"]) {
            command = [[thisArg mutableCopy] autorelease];
        }
        else  if ([@"-shell" isEqualToString:thisArg]) {
            shellType = TSShellDefault;
        }
        else if ([@"-dir" isEqualToString:thisArg]) {
            if (!(thisArg = [argsEnum nextObject])) usage();
            directory = thisArg;
        }
        else if ([@"-noclose" isEqualToString:thisArg]) {
            exitAction = TSDontCloseOnExit;
        }
        else if ([@"-env" isEqualToString:thisArg]) {
            environment = [[NSProcessInfo processInfo] environment];
        }
        else {
            usage();
        }
    }

    if (!directory) directory = [[NSFileManager defaultManager] currentDirectoryPath];
    if (!command) command = [NSMutableString stringWithCString:""];

    [terminal runCommand:command
        inputData:inputData
        outputData:&outputData
        errorData:&errorData
        waitForReturn:NO
        windowType:TSWindowNew
        windowHandle:&winHandle
        exitAction:exitAction
        shellType:shellType
        windowTitle:command
        directory:directory
        environment:environment
        returnCode:&returnCode];

    [pool release];

    exit(returnCode);
}
